<?php

class DispatchYeti {
    private function parseUrl($uri) {
    
    }
    
    public function dispatch($uri) {
        if(Yeti::config('controller.enable_route')) {
            $route = Yeti::factory('lib.route', 'Yeti', 'controller');
            $dispatch = $route->parseUrl($uri);
        }
        else {
            $dispatch = $this->parseUrl($uri);
        }
        
        if(empty($dispatch['controller'])) {
            throw new DispatchYetiException('controller_not_found');
        }
        
        try {
            Yeti::import("controller/" . $dispatch['controller']);
            
            $className = ucfirst($dispatch['controller']);
            if(stripos($className, '/') > 1) {
                $className = implode('', array_map('ucfirst', array_reverse(explode('/', $className))));
            }
            
            $nameControllerException = "{$className}ControllerYetiException";
            
            if(!class_exists($nameControllerException, FALSE)) {
                eval("class {$nameControllerException} extends ControllerYetiException {}");
            }
        }
        catch(YetiException $e) {
            throw new YetiException('controller_not_found', $e->getMessage());
        }
        
        $reflectionController = new ReflectionClass($className . "ControllerYeti");
        
        if($reflectionController->getConstant('ALLOW_PRODUCTION') == FALSE && Yeti::config('enviroment') == 'production') {
            throw new YetiException('controller_not_available');
            return FALSE;
        }
        
        if(!$reflectionController->isInstantiable() || !$reflectionController->isSubclassOf('ControllerYeti')) {
            throw new YetiException('controller_not_available');
            return FALSE;
        }
        
        if(!isset($dispatch['action']) || empty($dispatch['action'])) {
            $dispatch['action'] = 'index';
            //YETI_DEBUG AND yeti_debugger(__METHOD__, "Method 'main' setting for the controller", __FILE__, __LINE__);
        }
        
        $requestMethod = ucwords(strtolower($_SERVER['REQUEST_METHOD']));
        
        // Exists 'doXxx_method' (xxx = get/put/delete/post/head/options) and enable this?
        if(Yeti::config('controller.enable_use_requestmethod_in_action')
          AND in_array($requestMethod, Array('Get', 'Put', 'Delete', 'Post', 'Head', 'Options'))) {
            $requestMethodWithAct = "do{$requestMethod}_{$dispatch['action']}";
            
            if($reflectionController->hasMethod($requestMethod)) {
                $dispatch['action'] = $requestMethod;
            }
        }
        
        $reflectionMethod = $reflectionController->getMethod($dispatch['action']);
        
        if(!$reflectionMethod->isPublic() || $reflectionMethod->isAbstract() || $reflectionMethod->isStatic()) {
            throw new $nameControllerException('action_not_available');
            return FALSE;
        }
        
        $argsMethod = (isset($dispatch['params'])) ? $dispatch['params'] : Array();
        
        $controller = $reflectionController->newInstance(NULL);
        
        // Exists 'doXxx' (xxx = get/put/delete/post/head/options) and enable this?
        // This will be executed BEFORE others methods
        if(Yeti::config('controller.enable_execute_request_before_action')) {
            $requestMethod = "do{$requestMethod}";
            $controller->$requestMethod();
        }
        
        if(Yeti::config('controller.enable_callbacks_events')) {
            $controller->executeTriggerBefore();
        }
        
        if($controller->getExecMethod()) {
            $reflectionMethod->invokeArgs($controller, $argsMethod);
        }
        
        if(Yeti::config('controller.enable_callbacks_events')) {
            $controller->executeTriggerAfter();
        }        
    }
}